package service

import (
	"fmt"
	"net/http"
	"strconv"
	"time"
	"wrblog-api-go/app/common/constants"
	"wrblog-api-go/app/common/token"
	"wrblog-api-go/app/model/model_sys"
	"wrblog-api-go/app/service/service_sys"
	"wrblog-api-go/config"
	"wrblog-api-go/pkg/errs"
	"wrblog-api-go/pkg/redis"
	"wrblog-api-go/pkg/status"
	"wrblog-api-go/pkg/utils"
)

func LoginKey(loginForm token.LoginForm, clientInfo token.ClientInfo) (tokenInfo token.TokenInfo, err error) {
	val := redis.Get(fmt.Sprintf("%s%s", constants.LOGIN_AK, loginForm.Ak))
	loginNum, _ := strconv.Atoi(val)
	if loginNum >= 5 {
		err = errs.New(status.PreconditionFailed, fmt.Sprintf("密码错误次数超过五次，账户锁定%d分钟", constants.KEY_TIME))
	} else {
		if err = loginForm.LoginFormValidate(); err != nil {
			err = errs.Wrap(status.PreconditionFailed, err.Error(), err)
		}
	}
	if err != nil {
		return
	}
	var loginUser token.LoginUser
	switch loginForm.Lt {
	case "1":
		//账号密码登录逻辑
		privateKey := redis.Get(constants.RSA_KEY + loginForm.RkId)
		redis.Del(constants.RSA_KEY + loginForm.RkId)
		loginForm.Pk = utils.RsaDecrypt(loginForm.Pk, privateKey)
		loginUser, err = loginAk(loginForm, clientInfo)
		break
	case "2":
		loginUser, err = loginMk(loginForm, clientInfo)
		break
	case "3":
		loginUser, err = loginMbk(loginForm, clientInfo)
		break
	default:
		err = errs.New(status.NotAcceptable, "不支持的登录方式！")
	}
	if err != nil {
		return
	}
	tokenInfo = token.CreateToken(loginUser)
	return
}

// loginUk 账号密码登录
func loginAk(loginForm token.LoginForm, clientInfo token.ClientInfo) (loginUser token.LoginUser, err error) {
	isVerify, err := service_sys.GetValueByKey("sys:account:captchaEnabled")
	if err != nil {
		return
	}
	if isVerify == "true" {
		data := redis.Get(constants.CODE_KEY + loginForm.CkId)
		if utils.IsEmpty(data) {
			err = errs.New(status.PreconditionFailed, "验证码已过期！")
			return
		} else {
			if data != loginForm.Ck {
				err = errs.New(status.PreconditionFailed, "验证码错误！")
				return
			}
		}
	}
	sysUser, err := service_sys.GetUserByUk(loginForm.Ak)
	if utils.IsEmpty(sysUser) {
		if utils.VerifySpaceUrl(loginForm.Ak) {
			sysUser, err = service_sys.GetUserBySpaceUrl(loginForm.Ak)
		} else if utils.VerifyMobile(loginForm.Ak) {
			sysUser, err = service_sys.GetUserByMk(loginForm.Ak)
		} else if utils.VerifyMailBox(loginForm.Ak) {
			sysUser, err = service_sys.GetUserByMbk(loginForm.Ak)
		}
		if err != nil {
			return
		}
	}
	if utils.IsEmpty(sysUser) {
		err = errs.New(status.NoContent, "未查到用户信息！")
		return
	}
	if sysUser.Status != "0" {
		err = errs.New(http.StatusLocked, "用户状态异常，暂不可登录！")
		return
	}
	if !utils.CheckPasswordHash(loginForm.Pk, sysUser.Pk) {
		val := redis.Get(fmt.Sprintf("%s%s", constants.LOGIN_AK, loginForm.Ak))
		loginNum := 1
		if !utils.IsEmpty(val) {
			loginNum, _ = strconv.Atoi(val)
		}
		redis.SetTime(fmt.Sprintf("%s%s", constants.LOGIN_AK, loginForm.Ak), fmt.Sprintf("%d", loginNum+1), constants.KEY_TIME*time.Minute)
		err = errs.New(status.PreconditionFailed, "账号密码错误！")
		return
	}
	loginUser, err = getLoginUser(loginForm, clientInfo, sysUser)
	return
}

// LoginMk 手机号验证码登录
func loginMk(loginForm token.LoginForm, clientInfo token.ClientInfo) (loginUser token.LoginUser, err error) {
	ck := redis.Get(constants.CODE_KEY + loginForm.CkId)
	redis.Del(constants.CODE_KEY + loginForm.CkId)
	if utils.IsEmpty(ck) {
		err = errs.New(status.PreconditionFailed, "验证码已过期！")
	} else if ck != loginForm.Ck {
		err = errs.New(status.PreconditionFailed, "验证码错误！")
	} else {
		var sysUser model_sys.SysUserPo
		sysUser, err = service_sys.GetUserByMk(loginForm.Ak)
		if err != nil {
			return
		}
		if utils.IsEmpty(sysUser) {
			err = errs.New(status.NoContent, "未查到用户信息！")
			return
		}
		if sysUser.Status != "0" {
			err = errs.New(status.Locked, "用户状态异常，暂不可登录！")
			return
		}
		loginUser, err = getLoginUser(loginForm, clientInfo, sysUser)
	}
	return
}

// LoginMbk 邮箱验证码登录
func loginMbk(loginForm token.LoginForm, clientInfo token.ClientInfo) (loginUser token.LoginUser, err error) {
	ck := redis.Get(constants.CODE_KEY + loginForm.CkId)
	redis.Del(constants.CODE_KEY + loginForm.CkId)
	if utils.IsEmpty(ck) {
		err = errs.New(status.PreconditionFailed, "验证码已过期！")
	} else if ck != loginForm.Ck {
		err = errs.New(status.PreconditionFailed, "验证码错误！")
	} else {
		var sysUser model_sys.SysUserPo
		sysUser, err = service_sys.GetUserByMbk(loginForm.Ak)
		if err != nil {
			return
		}
		if utils.IsEmpty(sysUser) {
			err = errs.New(status.NoContent, "未查到用户信息！")
			return
		}
		if sysUser.Status != "0" {
			err = errs.New(status.Locked, "用户状态异常，暂不可登录！")
			return
		}
		loginUser, err = getLoginUser(loginForm, clientInfo, sysUser)
	}
	return
}

func getLoginUser(loginForm token.LoginForm, clientInfo token.ClientInfo, sysUser model_sys.SysUserPo) (token.LoginUser, error) {
	roles, err := service_sys.GetRolesByUserId(sysUser.UserId)
	permissions, err := service_sys.GetPermissionsByUserId(sysUser.UserId)
	return token.LoginUser{
		UserId:      sysUser.UserId,
		Uk:          sysUser.Uk,
		Ak:          loginForm.Ak,
		Roles:       roles,
		Permissions: permissions,
		LoginTime:   utils.GetNowDate(),
		ExpireTime:  config.Conf.ConfigInfo.Token.ExpireTime,
		ClientInfo:  clientInfo,
	}, err
}
